#ifndef _TRACK_LAYOUT_H_
#define _TRACK_LAYOUT_H_

#include <model.h>

#define NUM_TRAINS                      80

#define MSG_TRACK_NEXT_LANDMARK         0
#define MSG_TRACK_NEXT_SENSORS          1
#define MSG_TRACK_GET_SPEED             2
#define MSG_TRACK_UPDATE_SPEED          3
#define MSG_TRACK_WAIT_SPEED            4
#define MSG_TRACK_SENSOR_NEXT_LANDMARK  5
#define MSG_TRACK_GET_SWITCH            6
#define MSG_TRACK_UPDATE_SWITCH         7
#define MSG_TRACK_SWITCH_CURVED         8
#define MSG_TRACK_SWITCH_STRAIGHT       9
#define MSG_TRACK_SWITCH_AFTER_SWITCH   10
#define MSG_TRACK_WAIT_REVERSE          11
#define MSG_TRACK_UPDATE_REVERSE        12
#define MSG_TRACK_SHOULD_REVERSE        13
#define MSG_TRACK_GET_NODE              14

#define SENSOR_FORWARD 0
#define SENSOR_BACK    1

typedef struct __track_req {
  int type;
  int arg0;
  int arg1;
  int arg2;
  track_edge *next_sensors;
} track_req;

typedef struct __track_reply {
  int result;
  track_edge next;
  track_node node;
  char dir;
} track_reply;

void TrackManager();

/* Return the internal ID of the first-prediction next landmark */
// TODO: eventually, this will have to return multiple predictions.
int GetNextLandmark(int prev, int curr, track_edge *next);

/* Return the internal ID of the next landmark from the given sensor,
   provided that it was triggered in the given direction */
void GetNextDirectedLandmark(int sensor_id, int sensor_direction, track_edge *next);

void GetNextSensors(int sensor_id, int sensor_direction, int n,
  track_edge *next_sensors);

/* Update the current train speed. */
void UpdateTrainSpeed(int train_number, int train_speed);

/* Get the current train speed (non-blocking) */
int GetTrainSpeed(int train_number);

/* Get the current train speed (blocking) */
int WaitTrainSpeed(int train_number);

/* Get the current switch state */
int GetSwitchState(int switch_number);

/* Update the current switch state */
void UpdateSwitchState(int switch_number, int switch_dir);

int SwitchCurved(int curr, int next);

int SwitchStraight(int curr, int next);

int SwitchAfterSwitch(int sw, char *dir);

int ShouldReverse(int next, int oneAhead, int twoAhead);

void GetNode(int id, track_node *node);

#endif
